Skip to content

feat(libkernel): serve the sandbox CA bundle from host TLS roots - #5280

Merged
oneandonlydean merged 2 commits into
boykopovar:mainfrom
santhoshkumar-dev:codex/sandbox-ca-trust
Oct 17, 2026
Merged

oneandonlydean merged 2 commits into
boykopovar:mainfrom
santhoshkumar-dev:codex/sandbox-ca-trust

Conversation

@santhoshkumar-dev

@santhoshkumar-dev santhoshkumar-dev commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What

ProsperoRadio (PPSA99001) and SwanStation (PPSA98510) load /<sandbox word>/common/cert/CA_LIST.cer through bundled OpenSSL and cannot complete HTTPS requests when it is absent (#5001). This proposes serving a host-derived PEM bundle at that exact path. The host-trust design still awaits the maintainer decision in #5001.

The branch has two feature commits rebased onto main 8856f180c, with no merge commits. The first carries @screamm's implementation, as offered in #5001, retaining its author and coauthor attribution. The second adds:

  • Existing guest files, explicit aliases and blocked mounts take precedence over the exact-path provider.
  • The certificate path provider is checked before the relinked-module fallback, including for read-only opens.
  • Windows exports the current user's ROOT store, excludes certificates in Disallowed, and checks the combined EKU extension/property for TLS server authentication. CA intermediate certificates are not exported as roots.
  • In-memory Windows trust regressions and guest descriptor/stdio tests cover certificate filtering and file/alias/blocked-mount precedence.

Linux retains the original implementation's SSL_CERT_FILE/distribution-bundle selection. The bundle is created lazily as a read-only cache in the run directory; Windows certificate stores are opened read-only. Console CA contents/file format and complete Windows chain policy remain unverified and recorded in technical debt. Windows usage semantics follow CertGetEnhancedKeyUsage.

Tested

Rebased head f2ceed091, validated in the isolated PR checkout:

  • Windows 11, WinLibs GCC 15.2.0 UCRT r7, Ninja Release, BUILD_TESTING=ON: five tests pass (guest_sandbox_certificates, guest_sandbox_certificate_trust, guest_sandbox_random_word, guest_path_case, guest_working_directory).
  • Ubuntu 24.04 under WSL2, GCC 13.3, Release: six tests pass: the three applicable sandbox/path tests plus guest_working_directory, guest_exit_order and guest_path_lifetime.
  • Conventions and git diff --check pass. The certificate implementation and both certificate test files are byte-identical to the previous PR head 5f1b1fe01. The rebase preserves current-main path resolution, fix(libc): list the directory once for a missing path that may be a relinked module #6230, the merged fix(libc): preserve path services through process exit #4994 path-service lifetime fix and the host-stream source registration.

Earlier validation on e8f179733:

  • Full Windows build and all 125 patched runtime libraries passed, along with the test registration audit. After the former main merge at 8fd97c296, the Windows/Linux sandbox/path tests passed again.
  • The precedence regression failed against the original resolver; the trust regression failed with EKU filtering removed. Restoring each fix passed. In-memory stores check exact PEM/DER round trips, unrestricted/server/email/empty usage and explicit distrust without changing system stores.
  • Conditional Windows title runs used Windows 11, AMD Ryzen 5 5600X / Radeon RX 6700 XT (driver 32.0.21045.5002). Public package hashes were verified and unencrypted fSELF load segments reconstructed using the public payload SDK layout. A separate validation branch included fix(libkernel): report SO_ERROR and the other SOL_SOCKET options like FreeBSD #4796 (e6740bc6) and fix(libkernel): support POLLPRI on Windows sockets #4525 (5db1d8d5), excluded from this PR; fix(libkernel_sys): reach rename through a _nid_no_patch export #5025 was already on the base. With no manually supplied CA file and a 60-second limit, ProsperoRadio 01.000.010 downloaded three catalog pages and accepted 28,865 stations. SwanStation 1.2.4 wrote its game database and installed 1.2.5 (249 files), then reported Vulkan device loss; no rendering/gameplay stability claim. Both used an automatically generated 66-certificate bundle.

Independent contributor validation, attributed to @babyhuey's report on 8fd97c29 merged onto main f40b6930, Windows 11 / RTX 3080 / WinLibs GCC 15.2:

  • ProsperoLichess (PPSA99009, discussion ProsperoLichess (PPSA99009) #4982) changes from a missing CA file and curl error 77 to HTTPS status 200, with its daily puzzle and Lichess TV loading.
  • ProsperoRadio downloads all seven catalog pages, stores 59,440 stations in a 28.6 MB database, and displays the Popular grid on its next start.

No PS5 hardware or Linux title run was performed locally. Full Windows/Linux CI requires maintainer dispatch under the repository's workflow policy.

Checklist

@babyhuey

Copy link
Copy Markdown
Contributor

Two more titles on Windows 11 (RTX 3080, WinLibs GCC 15.2, Release), with this PR (8fd97c2) merged onto main f40b693 (clean merge), default flags:

  • ProsperoLichess (PPSA99009, discussion ProsperoLichess (PPSA99009) #4982). On main its HTTPS requests fail with ca=/gkbHtXc3Wq/common/cert/CA_LIST.cer (MISSING) and curl 77, so it stays in its offline mode. With this PR it logs ca=... (found) (libcurl 8.18.0, OpenSSL 3.5.2) and lichess probe status=200, with no curl 77. The daily puzzle (rating 2042, a real position) and Lichess TV (a live board) load, and the Offline pill gives way to "Not signed in".
  • ProsperoRadio (PPSA99001). It downloads the radio-browser catalog page by page (page offset=0 ... objects=10000 accepted=9512 through offset=60000 ... total=59440) into a 28.6 MB SQLite file. On the next start it shows "59,440 stations" with the Popular grid filled, at about 30 fps.

The bundle written to cert_cache/CA_LIST.cer was 93,926 bytes.

@oneandonlydean oneandonlydean self-assigned this Oct 14, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Please rebase on current main instead of merging it in; the branch has two merge commits. Serving the host's trust store as the console's CA_LIST.cer is a design call that is still open in #5001, so this waits on that.

@santhoshkumar-dev

Copy link
Copy Markdown
Contributor Author

Rebased onto main 31bfc4e86; head is 5f1b1fe01. There are now two feature commits and no merge commits, with @screamm's author/coauthor attribution preserved. The certificate implementation and both certificate test files are unchanged from the previous PR head.

Fresh-checkout validation passes: four Windows sandbox/path tests, the three applicable Ubuntu/WSL2 tests, conventions and the whitespace check. The description now distinguishes these checks from the earlier full build/title runs and credits @babyhuey's additional ProsperoLichess and ProsperoRadio results.

Agreed that serving host trust as CA_LIST.cer still awaits the design decision in #5001. This update addresses the branch history and does not claim that design is approved.

The overlap with #4994 is adjacent to Directories() in General.cpp: that PR retains the path services through exit; this one adds the exact-path provider. There is no implementation dependency. @krishalivaibhav, I can rebase this after #4994 if that should land first; please confirm the preferred merge order while #5001 remains pending.

AI-assisted: yes.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 14, 2026
@santhoshkumar-dev

santhoshkumar-dev commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor Author

@oneandonlydean, rebased this PR onto current main 8856f180c; the new head is f2ceed091, with two feature commits and no merge commits. The latest path resolver and #6230 are preserved, along with #4994's path-service lifetime fix, HostStreams.cpp registration and current Windows dependencies.

Validation on this head passes: five Windows tests and six Ubuntu/WSL2 tests, including the Linux guest_path_lifetime and guest_exit_order regressions, plus conventions and the whitespace check. The certificate implementation and its two test files are unchanged from 5f1b1fe01. The provider still serves this CA file on read-only opens, which current main routes through module lookup.

The new head's conventions check passes; its automatic build checks are running. Full Windows/Linux CI is skipped under the maintainer-dispatch policy and requires a maintainer dispatch.

The overlap scan finds no conflicting lines with other open PRs. #6061 is separate drive-letter path hardening, but it also changes resolver helpers this provider uses. If that refactor lands first, please retain this exact-path provider lookup when combining the changes; it is not listed as a functional dependency.

The design question in #5001 is also still open: host-derived trust at this exact guest path, or a shipped bundle? The title reports show that PEM works with bundled OpenSSL, while the console format and full Windows chain policy remain unverified in technical debt. If you approve the host-derived approach, please dispatch full Windows/Linux CI for PR 5280.

AI-assisted: yes.

@santhoshkumar-dev

Copy link
Copy Markdown
Contributor Author

@oneandonlydean, quick ping on the #5001 design decision: should AnyPS5 expose host-derived trust at CA_LIST.cer, or ship a CA bundle instead?

#5280 is rebased onto main 8856f180c; GitHub reports it clean and mergeable. Five Windows tests, six Linux tests and the automatic checks pass. The full Windows/Linux suites were skipped and need maintainer dispatch. The console CA format and complete Windows chain policy remain unknown, so I’m waiting on your direction before calling this ready to merge.

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 6061 core/libs/prx/libc/src/General.cpp L172-175

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 4972 core/libs/prx/libkernel/CMakeLists.txt
PR 5021 core/libs/prx/libc/src/General.cpp
core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 6044 core/libs/prx/libkernel/CMakeLists.txt
PR 6222 core/libs/prx/libc/src/General.cpp
core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 6228 core/libs/prx/libc/src/General.cpp
docs/dev/debt/libkernel.md
PR 6487 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 6510 docs/dev/debt/libkernel.md
PR 6710 docs/dev/debt/libkernel.md
PR 6836 docs/dev/debt/libkernel.md
PR 6879 core/libs/prx/libc/src/General.cpp

@jotitadev jotitadev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review on macOS, head f2ceed091, of the non-Windows branch of TrustedRoots.cpp / SandboxCertificates.cpp. Checked on the host, not with this PR's binary.

On macOS the provider finds no bundle, so CA_LIST.cer stays missing. None of the three fixed candidates exists on macOS 27.2:

$ ls /etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt /etc/ssl/ca-bundle.pem
ls: ...: No such file or directory   (all three)
$ grep -c 'BEGIN CERT' /etc/ssl/cert.pem
128

macOS ships its PEM bundle at /etc/ssl/cert.pem. That is also the path FreeBSD, OpenBSD/LibreSSL and Alpine use. Without SSL_CERT_FILE set, a macOS run behaves like main (CA_LIST.cer (MISSING)). The tests still pass because they set SSL_CERT_FILE, so they don't catch this.

Adding "/etc/ssl/cert.pem" to candidates would cover macOS. One caveat for the debt note: on macOS that file is a static snapshot. It does not reflect roots added to or distrusted in the Keychain, which is the same kind of gap the Windows section already notes for CTL restrictions.

This depends on the #5001 design decision, so treat it as input for whichever option is chosen.

Written with AI assistance (Claude Code). I ran the check above on my machine.

@coltken95

Copy link
Copy Markdown

Linux title runs (CachyOS, RTX 2070, NVIDIA driver), with f2ceed0 merged into main 5d9dcc4. Host bundle: /etc/ssl/certs/ca-certificates.crt (→ tls-ca-bundle.pem).

ProsperoTV (PPSA99003):

  • main: [ProsperoTV][http] https://iptv-org.github.io/iptv/index.m3u: Problem with the SSL CA cert (path? access rights?) (error adding trust anchors from file: /gkbHtXc3Wq/common/cert/CA_LIST.cer)
  • with this PR: no CA error, cert_cache/CA_LIST.cer (185 KB, read-only) is written, and the channel list loads (channel list shown).

PSXS5 (PPSA97510):

  • main: net: https://raw.githubusercontent.com/.../gamedb.yaml -> curl 77, http 0, then gamedb: download failed
  • with this PR: gamedb: index written and cert_cache/CA_LIST.cer is written (game list shown).

Both titles are the ones #5001 listed as expected to follow but not verified.

AI-assisted: yes (Claude Code)

@iDiesIrae-Req

Copy link
Copy Markdown

Windows title run for this PR: SwanStationPS5 (PPSA98510) 1.3.7 from the homebrew catalog, RTX 4070 Laptop, Windows 11 26300, WinLibs GCC 15.2.0 r7.

Build Update check (api.github.com) Game database (raw.githubusercontent.com)
main 5d9dcc4 curl 77, http 0 gamedb: download failed
main 5d9dcc4 + f2ceed0 update: latest 1.3.7, this 1.3.7 gamedb: index written (fresh cache/gamedb.txt, 1.1 MB)

With the PR the run directory gets cert_cache/CA_LIST.cer (99,724 bytes), and the title runs on at 60 FPS.

One thing to be aware of for the #5001 decision: during the passing run, Avast's HTTPS scanning was on, so both hosts were served a chain issued by "Avast Web/Mail Shield Root". It still verified, because that root is in the current user's ROOT store and this PR exports that store. So with host-derived trust, a title trusts whatever the PC trusts, including local TLS-inspection roots. A title that ships its own CA bundle instead (PSBox Cloud Gaming PPSA99810, assets/cacert.pem) rejects the same interception (certificate refused) and works once HTTPS scanning is off.

The main failure doesn't depend on Avast: the main row above was run with HTTPS scanning off, and it's curl's "can't read the CA file" (77).

AI-assisted: yes, Claude Code ran the builds and tests; I reviewed the results.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Host-derived trust is fine: serving the host's trust store as CA_LIST.cer unblocks these titles, and it's tested on Linux and Windows. Please rebase; it conflicts with main again.

screamm and others added 2 commits October 17, 2026 02:24
Titles that bundle OpenSSL load the console's CA file from the sandbox
directory and fail every HTTPS request without it. ProsperoRadio
(PPSA99001, libcurl 8.18.0 + OpenSSL 3.5.2) on main + boykopovar#4796 + boykopovar#4525:

  [ProsperoRadio][http] https://all.api.radio-browser.info/json/servers: Problem with the SSL CA cert (path? access rights?) (error adding trust anchors from file: /gkbHtXc3Wq/common/cert/CA_LIST.cer)

SwanStation (PPSA98510) stops on the same file (boykopovar#5001).

The guest path resolver now accepts exact-path providers, and libkernel
registers one for /<sceKernelGetFsSandboxRandomWord()>/common/cert/CA_LIST.cer.
On first use it writes a PEM bundle once per process to
cert_cache/CA_LIST.cer in the run directory, read-only: on Windows the
current user's ROOT and CA system stores, elsewhere SSL_CERT_FILE or the
first distro bundle that exists. Without a certificate the path keeps
resolving under the guest root and does not exist, as before. Every other
path under the sandbox word is unchanged. The console file's format and
the rest of its common/cert directory are unverified and recorded in
docs/dev/debt/libkernel.md.

With this change, boykopovar#4796, boykopovar#4525 and boykopovar#5025 on Windows 11, 60 s each:

  [ProsperoRadio][http] 11846160 bytes in 1458 ms: 1161 passes, 803 waits (679 woken) for 1428 ms
  [ProsperoRadio][catalog] page offset=0 bytes=11846160 objects=10000 accepted=9549 total=9549
  ...
  [ProsperoRadio][catalog] page offset=60000 bytes=1712035 objects=1494 accepted=1436 total=59371

  [SwanStationPS5] update: latest 1.2.5, this 1.1.3, available
  [SwanStationPS5] gamedb: index written

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@santhoshkumar-dev

Copy link
Copy Markdown
Contributor Author

@oneandonlydean, thanks for approving the host-derived approach. Rebased onto main 9bf01db66 and pushed head eb26fb97f with --force-with-lease. GitHub reports it mergeable. The branch still has two feature commits and no merge commits, with the original author/coauthor attribution preserved.

The Windows link conflict is resolved by retaining both main's iphlpapi dependency and this PR's crypt32. Current path/archive resolution and path-service lifetime behavior are preserved. I also addressed the macOS review by adding /etc/ssl/cert.pem and documenting that this static bundle does not reflect Keychain trust changes.

Fresh validation on Debian 13, GCC 14.2.0, Release: the affected libc and libkernel libraries build in an isolated out-of-tree project using their repository CMake source lists and pinned ZArchive/zstd dependencies. All seven existing sandbox/path/exit regressions pass, along with conventions and git diff --check. Windows trust code and both certificate test files are unchanged from f2ceed091; no native Windows/macOS build or title run was repeated for this head.

Automatic build checks are still running. Full Linux/Windows jobs were skipped under the maintainer-dispatch policy; please dispatch full CI for this head.

AI-assisted: yes.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 17, 2026
@oneandonlydean
oneandonlydean merged commit dfdc3de into boykopovar:main Oct 17, 2026
14 checks passed
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Merged, thanks @santhoshkumar-dev. One non-blocking follow-up if you have time: on Linux and macOS the bundle is served as the first file found (SSL_CERT_FILE first). A user-pointed SSL_CERT_FILE can hold more than certificates, such as a private key next to the chain, so it would be safer to copy only the BEGIN CERTIFICATE...END CERTIFICATE blocks into what the guest sees. A small separate PR is fine.

@MarcZX10

Copy link
Copy Markdown
Contributor

I opened PR #7007 for this follow-up. It filters the host bundle to complete certificate blocks and adds a regression with surrounding metadata and private-key blocks. The target builds and conventions/registration checks pass; focused CTest is blocked before assertions by this Linux runner's CPU feature guard, so I recorded that limitation and a passing standalone extraction harness in the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants